package com.aaa.project.commdetail.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.aaa.project.commdetail.domain.*;
import com.aaa.project.commdetail.mapper.DailyCommDetailMapper;
import com.aaa.project.commdetail.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ForkJoinPool;

/**
 * @author baibin
 * @version 1.0
 * @date 2025/4/22 17:09
 * @description DailyCommDetailServiceImpl
 */
@Service
public class DailyCommDetailServiceImpl implements DailyCommDetailService {

    private static final Logger log = LoggerFactory.getLogger(DailyCommDetailServiceImpl.class);

    @Resource
    private DailyCommDetailMapper dailyCommDetailMapper;
    @Resource
    private TempTimeStatService tempTimeStatService;
    @Resource
    private TempTimeStatOnlineNewService tempTimeStatOnlineNewService;
    @Resource
    private TempTimeStatOnlineNew2Service tempTimeStatOnlineNew2Service;


    @Override
    public void list(String userCityNo, String startTime, String stopTime) {
        log.info("userCityNo:{},startTime:{},stopTime:{}", userCityNo, startTime, stopTime);
        Date strartDate = DateUtil.parse(startTime, "yyyy-MM-dd");
        Date endDate = DateUtil.parse(stopTime, "yyyy-MM-dd");


        List<DailyCommDetail> list = dailyCommDetailMapper.list(userCityNo, strartDate, endDate);
        // 计算每条记录的 ONLINE 值
        for (DailyCommDetail detail : list) {
            calculateOnlineForRecord(detail);
        }
        log.info("success....");
    }

    private void calculateOnlineForRecord(DailyCommDetail detail) {
        Map<String, String> onlineMap = new HashMap<>();
        Date startTime = detail.getStartTime();
        Date stopTime = detail.getStopTime();
        // 如果 stopTime 早于 startTime，直接返回空
        if (stopTime.before(startTime)) {
            return;
        }

        // 获取 startTime 和 stopTime 的当天开始时间
        Date currentDay = DateUtil.beginOfDay(startTime);
        Date endDay = DateUtil.beginOfDay(stopTime);

        // 遍历从 startTime 当天到 stopTime 当天的每一天
        while (!currentDay.after(endDay)) {
            // 初始化当天的 ONLINE 字符串
            char[] online = new char[96];
            Arrays.fill(online, '0');

            // 计算当天的开始和结束时间
            Date dayStart = DateUtil.beginOfDay(currentDay);
            Date dayEnd = DateUtil.endOfDay(currentDay);

            // 计算记录在当天的时间范围
            Date recordStart = startTime.before(dayStart) ? dayStart : startTime;
            Date recordStop = stopTime.after(dayEnd) ? dayEnd : stopTime;

            // 计算 ONLINE 值
            for (int i = 0; i < 96; i++) {
                Date segmentStart = DateUtil.offsetMinute(dayStart, i * 15);
                Date segmentEnd = DateUtil.offsetMinute(segmentStart, 15);

                // 如果记录的时间段与当前 ONLINE 位有重叠，则设置为 1
                if (!recordStop.before(segmentStart) && !recordStart.after(segmentEnd)) {
                    online[i] = '1';
                }
            }

            // 将当天的 ONLINE 值存入 Map
            onlineMap.put(DateUtil.format(currentDay, "yyyy-MM-dd"), new String(online));
            TempTimeStat tempTimeStat = new TempTimeStat();
            tempTimeStat.setUserId(detail.getUserId());
            tempTimeStat.setOnline(new String(online));
            tempTimeStat.setParDay(currentDay);
            tempTimeStat.setUserCityNo(detail.getUserCityNo());
            tempTimeStat.setBrasPort(StrUtil.format("{}_{}", detail.getClientId(), detail.getCallinPhone()));
            tempTimeStatService.add(tempTimeStat);
            currentDay = DateUtil.offsetDay(currentDay, 1);
        }
        log.info("detail:{}", onlineMap.toString());
    }


    @Override
    public void listV2(String userCityNo, String startTime, String stopTime) {
        log.info("userCityNo:{},startTime:{},stopTime:{}", userCityNo, startTime, stopTime);
        // 获取开始时间和结束时间 解析开始结束时间，获取包含开始结束时间在内的所有日期
        Date startDate = DateUtil.parse(startTime, "yyyy-MM-dd");
        Date endDate = DateUtil.parse(stopTime, "yyyy-MM-dd");
        // 遍历从开始时间到结束时间的所有日期
        Date currentDate = startDate;
        while (!currentDate.after(endDate)) {
            // 根据开始时间和结束时间查询
            List<DailyCommDetail> list = dailyCommDetailMapper.list(userCityNo, currentDate, currentDate);
            // 计算每条记录的 ONLINE 值 ，然后插入到 TempTimeStatOnlineNew 表中的对应的96个字段中
            for (DailyCommDetail detail : list) {
                calculateOnlineForRecordV2(detail);
            }
            // 增加一天
            currentDate = DateUtil.offsetDay(currentDate, 1);
        }
        log.info("V2 success....");
    }

    private void calculateOnlineForRecordV2(DailyCommDetail detail) {
        Date startTime = detail.getStartTime();
        Date stopTime = detail.getStopTime();
        // 如果 stopTime 早于 startTime，直接返回空
        if (stopTime.before(startTime)) {
            return;
        }

        // 获取 startTime 和 stopTime 的当天开始时间
        Date currentDay = DateUtil.beginOfDay(startTime);
        Date endDay = DateUtil.beginOfDay(stopTime);

        // 遍历从 startTime 当天到 stopTime 当天的每一天
        while (!currentDay.after(endDay)) {
            // 初始化当天的 ONLINE 字符串
            char[] online = new char[96];
            Arrays.fill(online, '0');

            // 计算当天的开始和结束时间
            Date dayStart = DateUtil.beginOfDay(currentDay);
            Date dayEnd = DateUtil.endOfDay(currentDay);

            // 计算记录在当天的时间范围
            Date recordStart = startTime.before(dayStart) ? dayStart : startTime;
            Date recordStop = stopTime.after(dayEnd) ? dayEnd : stopTime;

            // 计算 ONLINE 值
            for (int i = 0; i < 96; i++) {
                Date segmentStart = DateUtil.offsetMinute(dayStart, i * 15);
                Date segmentEnd = DateUtil.offsetMinute(segmentStart, 15);

                // 如果记录的时间段与当前 ONLINE 位有重叠，则设置为 1
                if (!recordStop.before(segmentStart) && !recordStart.after(segmentEnd)) {
                    online[i] = '1';
                }
            }

            // 将当天的 ONLINE 值存入 Map
            TempTimeStatOnlineNew statOnlineNew = new TempTimeStatOnlineNew();
            statOnlineNew.setUserId(detail.getUserId());
            statOnlineNew.setParDay(currentDay);
            statOnlineNew.setUserCityNo(detail.getUserCityNo());
            statOnlineNew.setBrasPort(StrUtil.format("{}_{}", detail.getClientId(), detail.getCallinPhone()));
            // 将 ONLINE 值设置到 96 个字段中
            for (int i = 0; i < 96; i++) {
                setFieldValue(statOnlineNew, i + 1, String.valueOf(online[i]));
            }
            tempTimeStatOnlineNewService.add(statOnlineNew);
            currentDay = DateUtil.offsetDay(currentDay, 1);
        }
    }

    /**
     * 设置指定字段的值
     */
    private void setFieldValue(TempTimeStatOnlineNew vo, int index, String value) {
        try {
            java.lang.reflect.Field field = vo.getClass().getDeclaredField("online" + index);
            field.setAccessible(true);
            field.set(vo, value);
        } catch (Exception e) {
            log.error("设置字段值失败: online{}", index, e);
        }
    }


    @Override
    public void listV3(String userCityNo, String startTime, String stopTime) {
        log.info("v3 userCityNo:{},startTime:{},stopTime:{}", userCityNo, startTime, stopTime);
        // 获取开始时间和结束时间 解析开始结束时间，获取包含开始结束时间在内的所有日期
        Date startDate = DateUtil.parse(startTime, "yyyy-MM-dd");
        Date endDate = DateUtil.parse(stopTime, "yyyy-MM-dd");
        int parallelism = ForkJoinPool.commonPool().getParallelism();
        log.info("parallelism:{}", parallelism);
        // 并行处理每一天的数据
        List<DateTime> dates = DateUtil.rangeToList(startDate, endDate, DateField.DAY_OF_MONTH);
        // 记录开始时间
        long start = System.currentTimeMillis();
        dates.parallelStream().forEach(currentDate -> {
            // 根据开始时间和结束时间查询
            List<DailyCommDetail> list = dailyCommDetailMapper.list(userCityNo, currentDate, currentDate);
            // 计算每条记录的 ONLINE 值 ，然后插入到 TempTimeStatOnlineNew 表中的对应的96个字段中
            list.parallelStream().forEach(detail ->{
                List<TempTimeStatOnlineNew2> onlineNew2s = calculateOnlineForRecordV3(detail);
//                onlineNew2s.parallelStream().forEach(tempTimeStatOnlineNew2 -> {
//                    tempTimeStatOnlineNew2Service.add(tempTimeStatOnlineNew2);
//                });
                tempTimeStatOnlineNew2Service.batchAdd(onlineNew2s);
            });
        });
        // 记录结束时间
        long end = System.currentTimeMillis();
        // 计算耗时 秒
        log.info("总耗时：{} s", (end - start) / 1000);
        log.info("V3 success....");
    }

    private List<TempTimeStatOnlineNew2> calculateOnlineForRecordV3(DailyCommDetail detail) {
        Date startTime = detail.getStartTime();
        Date stopTime = detail.getStopTime();
        ConcurrentLinkedQueue<TempTimeStatOnlineNew2> resultQueue = new ConcurrentLinkedQueue<>();

        // 如果 stopTime 早于 startTime，直接返回空
        if (stopTime.before(startTime)) {
            return new ArrayList<>(resultQueue);
        }

        // 获取 startTime 和 stopTime 的当天开始时间
        Date startDay = DateUtil.beginOfDay(startTime);
        Date endDay = DateUtil.beginOfDay(stopTime);

        // 生成日期列表
        List<DateTime> dates = DateUtil.rangeToList(startDay, endDay, DateField.DAY_OF_MONTH);

        // 并行处理每一天的数据
        dates.parallelStream().forEach(currentDay -> {
            // 计算当天的开始和结束时间
            Date dayStart = DateUtil.beginOfDay(currentDay);
            Date dayEnd = DateUtil.endOfDay(currentDay);

            // 计算记录在当天的时间范围
            Date recordStart = startTime.before(dayStart) ? dayStart : startTime;
            Date recordStop = stopTime.after(dayEnd) ? dayEnd : stopTime;

            // 计算 ONLINE 值
            // 将当天的 ONLINE 值存入 TempTimeStatOnlineNew2
            TempTimeStatOnlineNew2 statOnlineNew = new TempTimeStatOnlineNew2();
            statOnlineNew.setUserId(detail.getUserId());
            statOnlineNew.setParDay(currentDay);
            statOnlineNew.setUserCityNo(detail.getUserCityNo());
            statOnlineNew.setBrasPort(StrUtil.format("{}_{}", detail.getClientId(), detail.getCallinPhone()));
            for (int i = 0; i < 96; i++) {
                Date segmentStart = DateUtil.offsetMinute(dayStart, i * 15);
                Date segmentEnd = DateUtil.offsetMinute(segmentStart, 15);

                // 如果记录的时间段与当前 ONLINE 位有重叠，则设置为 1
                if (!recordStop.before(segmentStart) && !recordStart.after(segmentEnd)) {
                    statOnlineNew.setOnline(i + 1, "1");
                } else {
                    statOnlineNew.setOnline(i + 1, null);
                }
            }
            // 将结果添加到队列中
            resultQueue.add(statOnlineNew);
        });
        return new ArrayList<>(resultQueue);
    }






}
